package com.ywd.platform.netty.config;

import com.ywd.platform.netty.properties.NettyProperties;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetSocketAddress;
import lombok.extern.slf4j.Slf4j;


/**
 * Netty服务器配置类
 */
@Slf4j
@AllArgsConstructor
@Configuration
public class NettyConfig {
    // ====================== 配置参数 ======================
    private final NettyProperties nettyProperties;
    private final JT808ChannelInitializer jt808ChannelInitializer;

    /**
     * 创建并配置ServerBootstrap bean
     * ServerBootstrap是Netty用于启动NIO服务端的辅助启动类
     */
    @Bean
    public ServerBootstrap serverBootstrap() {
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        // 配置服务器
        serverBootstrap
                .group(bossGroup(), workerGroup())                                         // 设置主从线程组
                .channel(NioServerSocketChannel.class)                                     // 设置通道类型为 NIO
                .childHandler(jt808ChannelInitializer)                                     // 设置通道初始化器(业务处理)

                // 服务器选项
                .option(ChannelOption.SO_BACKLOG, nettyProperties.getSoBacklog())          // 设置服务器接受连接的队列大小
                .option(ChannelOption.SO_REUSEADDR, nettyProperties.isSoReuseaddr())       // 启用端口复用

                // 客户端连接选项
                .childOption(ChannelOption.SO_KEEPALIVE, nettyProperties.isSoKeepalive())  // 设置保持活动连接
                .childOption(ChannelOption.TCP_NODELAY, nettyProperties.isTcpNodelay())    // 禁用Nagle算法

                // 背压控制
                .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK,
                        new WriteBufferWaterMark(
                                nettyProperties.getWriteBufferLowWaterMark(),
                                nettyProperties.getWriteBufferHighWaterMark()));

        return serverBootstrap;
    }

    /**
     * bossGroup线程组 - 用于接收客户端的连接请求
     * destroyMethod指定在bean销毁时调用shutdownGracefully方法优雅关闭
     */
    @Bean(destroyMethod = "shutdownGracefully")
    public EventLoopGroup bossGroup() {
        int threads = nettyProperties.getBossThreads();
        return new NioEventLoopGroup(threads, new DefaultThreadFactory("netty-boss"));
    }

    /**
     * Worker线程组 - 负责处理I/O操作
     * destroyMethod指定在bean销毁时调用shutdownGracefully方法优雅关闭
     */
    @Bean(destroyMethod = "shutdownGracefully")
    public EventLoopGroup workerGroup() {
        int threads = nettyProperties.getWorkerThreads();
        return new NioEventLoopGroup(threads, new DefaultThreadFactory("netty-worker"));
    }

    /**
     * 创建TCP socket地址
     * 指定服务器监听的端口号
     */
    @Bean
    public InetSocketAddress tcpSocketAddress() {
        return new InetSocketAddress(nettyProperties.getHost(), nettyProperties.getPort());
    }

}